import datetime
from enum import Enum, unique

from django.db import transaction
from django.http import JsonResponse
from django.views import View
from rest_framework import status, serializers
from rest_framework.parsers import JSONParser

from jqdelivery.error import UserExpressNullErr
from jqdelivery.models import (
    UserDeliveryOrder,
    UserDeliveryOrderGoods,
    UserDeliveryOrderState,
    UserPaymentType,
    UserExpressInfo,
    UserExpress,
)
from jqdelivery.serializers import UserExpressInfoSerializer
from jqexception.jqexecption import NullErr
from jqpackage.error import (
    ParameterNullErr,
    ParameterTypeErr,
    UserPackageCountNotEqualErr,
    UserPackageGoodsNullErr,
    UserPackageAlreadyDeliveryErr,
    UserPackageAlreadyRefinedErr,
    UserPackageAlreadyLockErr,
    UserPackageAlreadyUnhandledErr,
    UserExpressCountNotEqualErr,
)
from jqpackage.models import UserPackageGoods, UserPackageGoodsState
from jqpackage.serializers import (
    UserPackageGoodsV2Serializer,
    UserPackageGoodsSerializer,
)
from jqpage.pagination import JQPagination
from juqiadmin.auth import login_auth
from juqiadmin.common.filters import (
    EnumFilterResolver,
    ValueType,
    get_filters,
)
from juqiadmin.models import get_wxuser_recharge_withdraw_finance
from warehouse.models import JuqiGood
from wxcloudrun.models import get_web_settings
from wxcloudrun.views import order_uuid
from wxuser.error import UserPriceDeficitErr, UserNotExistentErr
from wxuser.models import (
    Users,
    UserRefinedOrder,
    UserRefinedOrderGoods,
    UserHunJingRecord,
    UserStoredMoneyRecord,
)
from wxuser.utli import get_current_user


@unique
class QueryMode(Enum):
    """查询模式"""

    unhandled = 0  # 未处理的
    lock = 1  # 上锁的


@unique
class SortMode(Enum):
    """排序方式"""

    latest = 0  # 最新的
    money_high = 1  # 价钱最高
    money_low = 2  # 价钱最低


@unique
class DisplayMode(Enum):
    all = 0  # 全部
    pile = 1  # 堆叠


class UserPackageGoodsView(View):
    _filters = {
        "query": EnumFilterResolver(QueryMode, value_type=ValueType.name),
        "sort": EnumFilterResolver(SortMode, value_type=ValueType.name),
        "display": EnumFilterResolver(DisplayMode),
    }

    @login_auth
    def get(self, request, *args, **kwargs):
        openid = request.META.get("HTTP_X_WX_OPENID", None)
        user = Users.objects.get(openid=openid)

        (query_mode, sort_mode, display) = get_filters(request, self._filters)

        if query_mode is None:
            query_mode = QueryMode.unhandled
        else:
            query_mode = QueryMode[query_mode]

        if sort_mode is None:
            sort_mode = SortMode.latest
        else:
            sort_mode = SortMode[sort_mode]

        if display is None:
            display = DisplayMode.all
        else:
            display = DisplayMode(display)

        _query_set = UserPackageGoods.objects.filter(deleted=False).filter(
            user_uuid=user.uuid
        )
        if query_mode == QueryMode.unhandled:
            _query_set = _query_set.filter(state=UserPackageGoodsState.unhandled)
        elif query_mode == QueryMode.lock:
            _query_set = _query_set.filter(state=UserPackageGoodsState.lock)

        if display == DisplayMode.all:
            _query_set = _query_set.extra(
                select={
                    "good_uuid": "JuqiGood.uuid",
                    "good_name": "JuqiGood.name",
                    "good_display_url": "JuqiGood.display_url",
                    "good_price": "JuqiGood.price",
                    "good_recovery_price": "JuqiGood.recovery_price",
                },
                tables=["JuqiGood"],
                where=[
                    "UserPackageGoods.good_uuid=JuqiGood.uuid",
                    "JuqiGood.deleted=false",
                ],
            ).values(
                "uuid",
                "user_uuid",
                "good_uuid",
                "good_name",
                "good_display_url",
                "game_type",
                "good_price",
                "good_recovery_price",
                "good_level_title",
                "createdAt",
            )

            if sort_mode == SortMode.latest:
                _query_set = _query_set.order_by("-createdAt")
            elif sort_mode == SortMode.money_high:
                _query_set = _query_set.order_by("-good_recovery_price")
            elif sort_mode == SortMode.money_low:
                _query_set = _query_set.order_by("good_recovery_price")

            pagination = JQPagination(UserPackageGoodsSerializer)

            _data = pagination.paginate(_query_set, request)
        elif display == DisplayMode.pile:
            _query_set = _query_set.extra(
                select={
                    "good_uuid": "JuqiGood.uuid",
                    "good_name": "JuqiGood.name",
                    "good_display_url": "JuqiGood.display_url",
                    "good_price": "JuqiGood.price",
                    "good_recovery_price": "JuqiGood.recovery_price",
                },
                tables=["JuqiGood"],
                where=[
                    "UserPackageGoods.good_uuid=JuqiGood.uuid",
                    "JuqiGood.deleted=false",
                ],
            ).values(
                "uuid",
                "user_uuid",
                "good_uuid",
                "good_name",
                "good_display_url",
                "game_type",
                "good_price",
                "good_recovery_price",
                "good_level_title",
                "createdAt",
            )
            _list_dict = dict()
            sum_count = 0
            for _item in _query_set:
                info: dict = _list_dict.get(_item.get("good_uuid"), None)
                if info is None:
                    info = {
                        "user_uuid": _item.get("user_uuid"),
                        "good_uuid": _item.get("good_uuid"),
                        "good_name": _item.get("good_name"),
                        "good_display_url": _item.get("good_display_url"),
                        "game_type": _item.get("game_type"),
                        "good_price": _item.get("good_price"),
                        "good_recovery_price": _item.get("good_recovery_price"),
                        "sum_good_price": 0,
                        "sum_good_recovery_price": 0,
                        "sum_count": 0,
                        "good_level_title": _item.get("good_level_title"),
                    }
                info["sum_good_price"] = info["sum_good_price"] + _item["good_price"]
                info["sum_good_recovery_price"] = (
                    info["sum_good_recovery_price"] + _item["good_recovery_price"]
                )
                info["sum_count"] = info["sum_count"] + 1
                _list_dict[_item.get("good_uuid")] = info
                sum_count += 1

            _list = list(_list_dict.values())

            _list.sort(key=lambda k: (k.get("sum_good_recovery_price")), reverse=True)

            _data = {"list": _list, "sum_count": sum_count}
            return JsonResponse(
                {"code": 0, "msg": "ok", "data": _data},
                status=status.HTTP_200_OK,
            )

        else:
            raise NullErr
        return JsonResponse(
            {"code": 0, "msg": "ok", "data": _data},
            status=status.HTTP_200_OK,
        )


def _get_package_goods_uuid_list(req_data):
    if req_data is None or req_data.get("goods") is None:
        raise ParameterNullErr
    user_package_goods_uuid_list = req_data.get("goods")
    if not isinstance(user_package_goods_uuid_list, list):
        raise ParameterTypeErr
    if len(user_package_goods_uuid_list) <= 0:
        raise ParameterNullErr
    return user_package_goods_uuid_list


def _get_express_info_uuid(req_data):
    if req_data is None or req_data.get("express_info_uuid") is None:
        raise ParameterNullErr
    user_express_info_uuid = req_data.get("express_info_uuid")
    if user_express_info_uuid is None:
        raise ParameterNullErr
    return user_express_info_uuid


def _get_pay_type(req_data):
    if req_data is None or req_data.get("pay_type") is None:
        raise ParameterNullErr
    pay_type = req_data.get("pay_type")
    if pay_type is None:
        raise ParameterNullErr
    if pay_type != "stored_money" and pay_type != "hunjing" and pay_type != "mixture":
        raise ParameterTypeErr
    return pay_type


def _get_remark(req_data):
    if req_data is None or req_data.get("remark") is None:
        return ""
    remark = req_data.get("remark")
    return remark


def _user_package_goods_list(user, user_package_goods_uuid_list, state):
    _user_package_goods_uuid_list = list(set(user_package_goods_uuid_list))
    user_package_list = (
        UserPackageGoods.objects.filter(deleted=False)
        .filter(user_uuid=user.uuid)
        .filter(state=state)
        .filter(uuid__in=user_package_goods_uuid_list)
    )
    if user_package_list.count() != len(user_package_goods_uuid_list):
        raise UserPackageCountNotEqualErr
    return user_package_list


def _user_good_uuid_by_user_package_list(user, good_list, state):
    if good_list is None or len(good_list) <= 0:
        raise ParameterNullErr
    user_package_list = []
    for good in good_list:
        uuid = good.get("uuid")
        count = good.get("count")
        if uuid is None or count is None:
            raise ParameterNullErr
        _package_uuid_list = (
            UserPackageGoods.objects.filter(user_uuid=user.uuid)
            .filter(state=state)
            .filter(good_uuid=uuid)
            .values("uuid")[:count]
        )
        for _package_uuid in _package_uuid_list:
            user_package_list.append(_package_uuid.get("uuid"))
    if len(user_package_list) <= 0:
        raise UserPackageGoodsNullErr
    return user_package_list


def _check_delivery(user, user_package_goods_uuid_list):
    delivery_count = (
        UserPackageGoods.objects.filter(deleted=False)
        .filter(user_uuid=user.uuid)
        .filter(state=UserPackageGoodsState.delivery)
        .filter(uuid__in=user_package_goods_uuid_list)
        .count()
    )
    if delivery_count > 0:  # 检查是否包含已经发货的赏品
        raise UserPackageAlreadyDeliveryErr


def _check_refined(user, user_package_goods_uuid_list):
    refined_count = (
        UserPackageGoods.objects.filter(deleted=False)
        .filter(user_uuid=user.uuid)
        .filter(state=UserPackageGoodsState.refined)
        .filter(uuid__in=user_package_goods_uuid_list)
        .count()
    )
    if refined_count > 0:  # 检查是否包含已经被提炼的赏品
        raise UserPackageAlreadyRefinedErr


def _check_lock(user, user_package_goods_uuid_list):
    lock_count = (
        UserPackageGoods.objects.filter(deleted=False)
        .filter(user_uuid=user.uuid)
        .filter(state=UserPackageGoodsState.lock)
        .filter(uuid__in=user_package_goods_uuid_list)
        .count()
    )
    if lock_count > 0:  # 检查是否包含保险袋赏品
        raise UserPackageAlreadyLockErr


def _check_unhandled(user, user_package_goods_uuid_list):
    lock_count = (
        UserPackageGoods.objects.filter(deleted=False)
        .filter(user_uuid=user.uuid)
        .filter(state=UserPackageGoodsState.unhandled)
        .filter(uuid__in=user_package_goods_uuid_list)
        .count()
    )
    if lock_count > 0:  # 检查是否包含保险袋赏品
        raise UserPackageAlreadyUnhandledErr


def _update_package_goods_list_state(package_goods_list, state):
    new_user_package_list = []
    for package_goods in package_goods_list:
        package_goods.state = state
        new_user_package_list.append(package_goods)
    UserPackageGoods.objects.bulk_update(
        new_user_package_list,
        fields=["state"],
        batch_size=len(new_user_package_list),
    )  # 更新状态
    return len(new_user_package_list)


def _get_delivery_price(sum_count, sum_recovery_price):
    """计算运费"""
    web_settings = get_web_settings()
    if (
        sum_count < web_settings.goods_less_count
        and sum_recovery_price < web_settings.goods_recycle_less_money
    ):
        return web_settings.goods_freight_money
    return 0


class UserPackageRefinedView(View):
    # 前台提炼接口
    @login_auth
    @transaction.atomic()
    def put(self, request, *args, **kwargs):
        req_data: dict = JSONParser().parse(request)

        display = req_data.get("display")

        if display is None:
            display = 0

        _display = DisplayMode(display)

        user_package_goods_uuid_list = _get_package_goods_uuid_list(req_data)
        openid = request.META.get("HTTP_X_WX_OPENID", None)
        if openid is None:
            raise UserNotExistentErr
        user = Users.objects.filter(openid=openid).select_for_update().first()
        if user is None:
            raise UserNotExistentErr

        if _display == DisplayMode.pile:
            user_package_goods_uuid_list = _user_good_uuid_by_user_package_list(
                user, user_package_goods_uuid_list, UserPackageGoodsState.unhandled
            )
        _check_lock(user, user_package_goods_uuid_list)
        _check_refined(user, user_package_goods_uuid_list)
        _check_delivery(user, user_package_goods_uuid_list)
        user_package_list = _user_package_goods_list(
            user, user_package_goods_uuid_list, UserPackageGoodsState.unhandled
        )

        refined_order = UserRefinedOrder.objects.create(  # 创建提炼订单
            orderid=order_uuid("TL_"), user_uuid=user.uuid
        )

        new_user_package_list = []
        sum_amount = 0
        create_user_refined_order_goods = []
        user_package_good_uuid_list = []
        for user_package in user_package_list:
            user_package_good_uuid_list.append(user_package.good_uuid)
        user_package_good_uuid_list = list(set(user_package_good_uuid_list))
        goods_list = JuqiGood.objects.filter(uuid__in=user_package_good_uuid_list)
        goods_list_dict = {}

        for goods in goods_list:
            if goods is None:
                raise UserPackageGoodsNullErr
            goods_list_dict[goods.uuid] = goods

        for user_package in user_package_list:
            refined_order.sale_count += 1
            goods = goods_list_dict.get(user_package.good_uuid)

            if goods is None:
                raise UserPackageGoodsNullErr

            sum_amount += goods.recovery_price  # 计算一共提炼的总价值
            refined_order.sale_money += goods.recovery_price  # 计算一共可以提炼多少魂晶

            create_user_refined_order_goods.append(
                UserRefinedOrderGoods(
                    order_refined_uuid=refined_order.uuid,
                    user_package_uuid=user_package.uuid,
                    good_uuid=goods.uuid,
                )
            )
            user_package.state = UserPackageGoodsState.refined
            new_user_package_list.append(user_package)

        refined_order.save()

        UserRefinedOrderGoods.objects.bulk_create(create_user_refined_order_goods)
        UserPackageGoods.objects.bulk_update(
            new_user_package_list,
            fields=["state"],
            batch_size=len(new_user_package_list),
        )  # 更新状态

        _old = user.hunjing
        _new = _old + refined_order.sale_money
        user.hunjing = _new
        user.package_amount = user.package_amount - sum_amount  # 减少赏柜总价值
        _record = {
            "user_uuid": user.uuid,
            "hunjing": refined_order.sale_money,
            "old_hunjing": _old,
            "new_hunjing": _new,
            "detail": f"提炼{refined_order.sale_count}个物品",
        }
        UserHunJingRecord(**_record).save()
        user.hunjing = _new
        user.save()

        return JsonResponse(
            {
                "code": 0,
                "msg": "ok",
                "data": {
                    "sale_money": refined_order.sale_money,
                    "sale_count": refined_order.sale_count,
                },
            },
            status=status.HTTP_200_OK,
        )


class UserPackageLockView(View):
    # 前台移入保险箱接口
    @login_auth
    @transaction.atomic()
    def put(self, request, *args, **kwargs):
        req_data: dict = JSONParser().parse(request)
        display = req_data.get("display")

        if display is None:
            display = 0

        _display = DisplayMode(display)
        user_package_goods_uuid_list = _get_package_goods_uuid_list(req_data)
        openid = request.META.get("HTTP_X_WX_OPENID", None)
        if openid is None:
            raise UserNotExistentErr
        user = Users.objects.filter(openid=openid).select_for_update().first()
        if user is None:
            raise UserNotExistentErr
        if _display == DisplayMode.pile:
            user_package_goods_uuid_list = _user_good_uuid_by_user_package_list(
                user, user_package_goods_uuid_list, UserPackageGoodsState.unhandled
            )
        _check_lock(user, user_package_goods_uuid_list)
        _check_refined(user, user_package_goods_uuid_list)
        _check_delivery(user, user_package_goods_uuid_list)
        package_goods_list = _user_package_goods_list(
            user, user_package_goods_uuid_list, UserPackageGoodsState.unhandled
        )
        lock_num = _update_package_goods_list_state(
            package_goods_list, UserPackageGoodsState.lock
        )

        return JsonResponse(
            {
                "code": 0,
                "msg": "ok",
                "data": {
                    "lock_num": lock_num,
                },
            },
            status=status.HTTP_200_OK,
        )


class UserPackageUnlockView(View):
    # 前台移出保险箱接口
    @login_auth
    @transaction.atomic()
    def put(self, request, *args, **kwargs):
        req_data: dict = JSONParser().parse(request)
        user_package_goods_uuid_list = _get_package_goods_uuid_list(req_data)
        openid = request.META.get("HTTP_X_WX_OPENID", None)
        if openid is None:
            raise UserNotExistentErr
        user = Users.objects.filter(openid=openid).select_for_update().first()
        if user is None:
            raise UserNotExistentErr
        display = req_data.get("display")

        if display is None:
            display = 0

        _display = DisplayMode(display)
        if _display == DisplayMode.pile:
            user_package_goods_uuid_list = _user_good_uuid_by_user_package_list(
                user, user_package_goods_uuid_list, UserPackageGoodsState.lock
            )
        _check_refined(user, user_package_goods_uuid_list)
        _check_delivery(user, user_package_goods_uuid_list)
        _check_unhandled(user, user_package_goods_uuid_list)
        package_goods_list = _user_package_goods_list(
            user, user_package_goods_uuid_list, UserPackageGoodsState.lock
        )
        unlock_num = _update_package_goods_list_state(
            package_goods_list, UserPackageGoodsState.unhandled
        )

        return JsonResponse(
            {
                "code": 0,
                "msg": "ok",
                "data": {
                    "unlock_num": unlock_num,
                },
            },
            status=status.HTTP_200_OK,
        )


def _check_express(user, user_express_uuid):
    _count = (
        UserExpressInfo.objects.filter(deleted=False)
        .filter(user_uuid=user.uuid)
        .filter(uuid=user_express_uuid)
        .count()
    )
    if _count <= 0:  # 检查是否存在这个地址信息
        raise UserExpressCountNotEqualErr


class UserPackageApplyDeliveryView(View):
    # 小程序发货确认
    @login_auth
    @transaction.atomic()
    def put(self, request, *args, **kwargs):
        """
        {
            "goods": [],
        }
        """
        req_data: dict = JSONParser().parse(request)
        user_package_goods_uuid_list = _get_package_goods_uuid_list(req_data)

        # user = get_current_user(request, False)
        openid = request.META.get("HTTP_X_WX_OPENID", None)
        if openid is None:
            raise UserNotExistentErr
        user = Users.objects.filter(openid=openid).select_for_update().first()
        if user is None:
            raise UserNotExistentErr

        display = req_data.get("display")

        if display is None:
            display = 0

        _display = DisplayMode(display)
        if _display == DisplayMode.pile:
            user_package_goods_uuid_list = _user_good_uuid_by_user_package_list(
                user, user_package_goods_uuid_list, UserPackageGoodsState.unhandled
            )
        _check_lock(user, user_package_goods_uuid_list)
        _check_refined(user, user_package_goods_uuid_list)
        _check_delivery(user, user_package_goods_uuid_list)

        _query_set = (
            UserPackageGoods.objects.filter(deleted=False)
            .filter(user_uuid=user.uuid)
            .filter(state=UserPackageGoodsState.unhandled)
            .filter(uuid__in=user_package_goods_uuid_list)
        )

        _query_set = _query_set.extra(
            select={
                "good_uuid": "JuqiGood.uuid",
                "good_name": "JuqiGood.name",
                "good_display_url": "JuqiGood.display_url",
                "good_price": "JuqiGood.price",
                "good_recovery_price": "JuqiGood.recovery_price",
            },
            tables=["JuqiGood"],
            where=[
                "UserPackageGoods.good_uuid=JuqiGood.uuid",
                "JuqiGood.deleted=false",
            ],
        ).values(
            "uuid",
            "user_uuid",
            "good_uuid",
            "good_name",
            "good_display_url",
            "game_type",
            "good_price",
            "good_recovery_price",
            "good_level_title",
            "createdAt",
        )

        _query_set = _query_set.order_by("-good_recovery_price")

        _good_all = _query_set.all()

        _good_list = []
        sum_count = 0
        sum_price = 0
        sum_recovery_price = 0
        _good_list_dict = {}

        for _good in _good_all:
            good_uuid = _good.get("good_uuid")

            _good_dict = _good_list_dict.get(good_uuid)
            if _good_dict is None:
                _good_dict = {
                    "user_uuid": _good.get("user_uuid"),
                    "good_uuid": _good.get("good_uuid"),
                    "good_name": _good.get("good_name"),
                    "good_display_url": _good.get("good_display_url"),
                    "game_type": _good.get("game_type"),
                    "good_price": _good.get("good_price"),
                    "good_recovery_price": _good.get("good_recovery_price"),
                    "good_level_title": _good.get("good_level_title"),
                    "sum_good_price": 0,
                    "sum_good_recovery_price": 0,
                    "sum_good_count": 0,
                }
            _good_dict["sum_good_price"] += _good.get("good_price")
            _good_dict["sum_good_recovery_price"] += _good.get("good_recovery_price")
            _good_dict["sum_good_count"] += 1
            sum_count += 1
            sum_price += _good.get("good_price")
            sum_recovery_price += _good.get("good_recovery_price")
            _good_list_dict[good_uuid] = _good_dict

        for _good_dict in _good_list_dict.values():
            _good_list.append(UserPackageGoodsV2Serializer(_good_dict).data)

        delivery_price = _get_delivery_price(sum_count, sum_recovery_price)  # 计算运费

        user_express = (
            UserExpress.objects.filter(deleted=False)
            .filter(user_uuid=user.uuid)
            .first()
        )  # 获取默认地址

        user_express_info_data = None
        if user_express is None:
            raise UserExpressNullErr
        if user_express.default_uuid is not None:
            user_express_info = (
                UserExpressInfo.objects.filter(deleted=False)
                .filter(uuid=user_express.default_uuid)
                .first()
            )
            if user_express_info is not None:
                user_express_info_data = UserExpressInfoSerializer(
                    user_express_info
                ).data
        else:
            user_express_info = (
                UserExpressInfo.objects.filter(deleted=False)
                .filter(express_uuid=user_express.uuid)
                .filter(user_uuid=user.uuid)
                .first()
            )
            if user_express_info is not None:
                user_express_info_data = UserExpressInfoSerializer(
                    user_express_info
                ).data

        package_goods_uuid_list = []
        uuid_field = serializers.UUIDField()
        for package_goods_uuid in user_package_goods_uuid_list:
            package_goods_uuid_list.append(
                uuid_field.to_representation(package_goods_uuid)
            )

        return JsonResponse(
            {
                "code": 0,
                "msg": "ok",
                "data": {
                    "goods": _good_list,
                    "package_goods_uuid": package_goods_uuid_list,
                    "sum_count": sum_count,
                    "sum_price": sum_price,
                    "sum_recovery_price": sum_recovery_price,
                    "user_express": user_express_info_data,
                    "delivery_price": delivery_price,
                },
            },
            status=status.HTTP_200_OK,
        )


class UserPackageDeliveryView(View):
    # 小程序发货接口

    @login_auth
    @transaction.atomic()
    def put(self, request, *args, **kwargs):
        """
        {
            "express_info_uuid": "",
            "goods": [],
            "pay_type": "stored_money" | "hunjing",
            "remark": ""
        }
        """
        req_data: dict = JSONParser().parse(request)
        user_package_goods_uuid_list = _get_package_goods_uuid_list(req_data)
        user_express_info_uuid = _get_express_info_uuid(req_data)
        remark = _get_remark(req_data)
        openid = request.META.get("HTTP_X_WX_OPENID", None)
        if openid is None:
            raise UserNotExistentErr
        user = Users.objects.filter(openid=openid).select_for_update().first()
        if user is None:
            raise UserNotExistentErr
        display = req_data.get("display")

        if display is None:
            display = 0

        _display = DisplayMode(display)
        if _display == DisplayMode.pile:
            user_package_goods_uuid_list = _user_good_uuid_by_user_package_list(
                user, user_package_goods_uuid_list, UserPackageGoodsState.unhandled
            )
        _check_express(user, user_express_info_uuid)
        _check_lock(user, user_package_goods_uuid_list)
        _check_refined(user, user_package_goods_uuid_list)
        _check_delivery(user, user_package_goods_uuid_list)
        user_package_list = _user_package_goods_list(
            user, user_package_goods_uuid_list, UserPackageGoodsState.unhandled
        )

        delivery_order = UserDeliveryOrder.objects.create(  # 创建发货订单
            orderid=order_uuid("FH_"),
            user_uuid=user.uuid,
            user_express_info_uuid=user_express_info_uuid,
        )

        new_user_package_list = []
        sum_recovery_price = 0
        sum_price = 0
        sum_count = 0
        create_user_delivery_order_goods = []
        _now = datetime.datetime.now()
        user_package_good_uuid_list = []
        for user_package in user_package_list:
            user_package_good_uuid_list.append(user_package.good_uuid)
        user_package_good_uuid_list = list(set(user_package_good_uuid_list))
        goods_list = JuqiGood.objects.filter(uuid__in=user_package_good_uuid_list)
        goods_list_dict = {}

        for goods in goods_list:
            if goods is None:
                raise UserPackageGoodsNullErr
            goods_list_dict[goods.uuid] = goods

        for user_package in user_package_list:
            goods = goods_list_dict.get(user_package.good_uuid)
            if goods is None:
                raise UserPackageGoodsNullErr

            sum_recovery_price += goods.recovery_price  # 计算发货成本价值
            sum_price += goods.price
            sum_count += 1
            create_user_delivery_order_goods.append(
                UserDeliveryOrderGoods(
                    delivery_order_uuid=delivery_order.uuid,
                    user_package_uuid=user_package.uuid,
                    good_uuid=goods.uuid,
                )
            )

            user_package.state = UserPackageGoodsState.delivery  # 把背包物品设置成发货状态
            new_user_package_list.append(user_package)

        delivery_price = _get_delivery_price(sum_count, sum_recovery_price)  # 运费
        delivery_order.sum_recovery_price = sum_recovery_price  # 发货成本价值
        delivery_order.sum_price = sum_price  # 计算一共发货价值
        delivery_order.sum_count = sum_count
        delivery_order.state = UserDeliveryOrderState.unshipped  # 默认未发货
        delivery_order.createdAt = _now  # 订单创建时间
        delivery_order.pay_datetime = _now  # 订单支付时间
        delivery_order.delivery_price = delivery_price  # 运费
        delivery_order.actual_price = delivery_price  # 算上运费
        delivery_order.user_uuid = user.uuid
        delivery_order.remark = remark

        if delivery_price > 0:  # 开始扣除运费
            pay_type = _get_pay_type(req_data)
            if pay_type == "stored_money":
                delivery_order.pay_type = UserPaymentType.stored_money  # 余额支付
                _old = user.stored_money
                _new = _old - delivery_price
                if _new <= 0:
                    raise UserPriceDeficitErr
                user.stored_money = _new
                _record = {
                    "user_uuid": user.uuid,
                    "stored_money": delivery_price,
                    "old_stored_money": _old,
                    "new_stored_money": _new,
                    "detail": f"运费消耗{delivery_price / 100}",
                }
                UserStoredMoneyRecord(**_record).save()
            elif pay_type == "hunjing":
                delivery_order.pay_type = UserPaymentType.hunjing  # 魂晶支付

                _old = user.hunjing
                _new = _old - delivery_price

                if _new <= 0:
                    raise UserPriceDeficitErr

                user.hunjing = _new
                _record = {
                    "user_uuid": user.uuid,
                    "hunjing": delivery_price,
                    "old_hunjing": _old,
                    "new_hunjing": _new,
                    "detail": f"运费消耗{delivery_price / 100}",
                }
                UserHunJingRecord(**_record).save()
            else:
                raise ParameterTypeErr
        else:
            delivery_order.pay_type = UserPaymentType.free  # 免运费

        user.package_amount -= sum_recovery_price  # 去除赏柜总价值
        user.delivery_amount += sum_recovery_price  # 增加发货总价值
        finance = get_wxuser_recharge_withdraw_finance(user.uuid)
        finance.all_delivery_amount += sum_recovery_price  # 计算每日发货总价值
        finance.save()
        UserDeliveryOrderGoods.objects.bulk_create(create_user_delivery_order_goods)
        UserPackageGoods.objects.bulk_update(
            new_user_package_list,
            fields=["state"],
            batch_size=len(new_user_package_list),
        )  # 更新状态
        delivery_order.save()
        user.save()

        return JsonResponse(
            {
                "code": 0,
                "msg": "ok",
                "data": {
                    "delivery_price": delivery_price,
                    "sum_count": sum_count,
                    "sum_price": sum_price,
                    "sum_recovery_price": sum_recovery_price,
                },
            },
            status=status.HTTP_200_OK,
        )


# class UserPackageCancelDeliveryView(View):
#     @login_auth
#     @transaction.atomic()
#     def put(self, request, *args, **kwargs):
#         user = get_current_user(request, False)
#         uuid_resolver = StringFilterResolver()
#         uuid = uuid_resolver.resolve_argument("uuid", request)
#         if uuid is None:
#             raise UserDeliveryNullErr
#         delivery_order = UserDeliveryOrder.objects.filter(deleted=False).filter(uuid=uuid).first()
#         if delivery_order is None:
#             raise UserDeliveryNullErr
#
